`include "top.vh"

module mycpu_top(
    input  wire        clk,
    input  wire        resetn,
    // inst sram interface
    output        inst_sram_req,
    output [ 3:0] inst_sram_wstrb,
    output        inst_sram_wr,
    output [31:0] inst_sram_addr,
    output [31:0] inst_sram_wdata,
    input  [31:0] inst_sram_rdata,
    output [1 :0] inst_sram_size,
    input         inst_sram_addr_ok,
    input         inst_sram_data_ok,
    // data sram interface
    output        data_sram_req,
    output [ 3:0] data_sram_wstrb,
    output        data_sram_wr,
    output [31:0] data_sram_addr,
    output [31:0] data_sram_wdata,
    input  [31:0] data_sram_rdata,
    output [1 :0] data_sram_size,
    input         data_sram_addr_ok,
    input         data_sram_data_ok,
    // trace debug interface
    output wire [31:0] debug_wb_pc,
    output wire [ 3:0] debug_wb_rf_we,
    output wire [ 4:0] debug_wb_rf_wnum,
    output wire [31:0] debug_wb_rf_wdata
);
wire    reset;
assign  reset = ~resetn;

wire         ds_allowin;
wire         es_allowin;
wire         ms_allowin;
wire         ws_allowin;

wire         fs_to_ds_valid;
wire         ds_to_es_valid;
wire         es_to_ms_valid;
wire         ms_to_ws_valid;

//csr read & write
wire [13:0]  csr_num;
wire [31:0]  csr_rvalue;
wire         csr_we;
wire [31:0]  csr_wvalue;
wire [31:0]  csr_wmask;

//pipeline
wire [`fs_2_ds_bus_wid - 1:0] fs_to_ds_bus;
wire [`ds_2_es_bus_wid - 1:0] ds_to_es_bus;
wire [`es_2_ms_bus_wid - 1:0] es_to_ms_bus;
wire [`ms_2_ws_bus_wid - 1:0] ms_to_ws_bus;
//branch
wire [33:0] br_bus;
//read after write
wire [38:0] es_to_id_bus;
wire [38:0] ms_to_id_bus;
wire [38:0] ws_to_id_bus;
//interrupt
wire has_int;
//ws_ex
wire ms_ex, ws_ex;
wire ms_ertn_flush, ws_ertn_flush;
wire [31:0] ex_entry;
wire [31:0] era_entry;
wire [31:0] ws_vaddr;
wire [ 5:0] ws_ecode;
wire [ 8:0] ws_esubcode;
//csr data confilct
wire es_read_csr, ms_read_csr, ws_read_csr;

// IF stage
if_stage if_stage(
    .clk            (clk            ),
    .reset          (reset          ),
    //allowin
    .ds_allowin     (ds_allowin     ),
    //brbus
    .br_bus         (br_bus         ),
    //outputs
    .fs_to_ds_valid (fs_to_ds_valid ),
    .fs_to_ds_bus   (fs_to_ds_bus   ),
    // inst sram interface
    .inst_sram_req  (inst_sram_req  ),
    .inst_sram_wr   (inst_sram_wr   ),
    .inst_sram_wstrb(inst_sram_wstrb),
    .inst_sram_addr (inst_sram_addr ),
    .inst_sram_wdata(inst_sram_wdata),
    .inst_sram_rdata(inst_sram_rdata),
    .inst_sram_size (inst_sram_size ),
    .inst_sram_addr_ok(inst_sram_addr_ok),
    .inst_sram_data_ok(inst_sram_data_ok),
    //ex
    .ws_ex          (ws_ex          ),
    .ex_entry       (ex_entry       ),
    .ws_ertn_flush     (ws_ertn_flush     ),
    .era_entry      (era_entry      )
);
// ID stage
id_stage id_stage(
    .clk            (clk            ),
    .reset          (reset          ),
    //allowin
    .es_allowin     (es_allowin     ),
    .ds_allowin     (ds_allowin     ),
    //from fs
    .fs_to_ds_valid (fs_to_ds_valid ),
    .fs_to_ds_bus   (fs_to_ds_bus   ),
    //from es
    .es_to_id_bus (es_to_id_bus),
    //from ms
    .ms_to_id_bus (ms_to_id_bus),
    //to es
    .ds_to_es_valid (ds_to_es_valid ),
    .ds_to_es_bus   (ds_to_es_bus   ),
    //to fs
    .br_bus         (br_bus         ),
    //to rf: for write back
    .ws_to_id_bus   (ws_to_id_bus   ),
    //csr data conflict
    .es_ms_ws_read_csr({es_read_csr, ms_read_csr, ws_read_csr}),
    //ex
    .has_int        (has_int        ),
    .ws_ex          (ws_ex          ),
    .ws_ertn_flush     (ws_ertn_flush     )
);
// EXE stage
exe_stage exe_stage(
    .clk            (clk            ),
    .reset          (reset          ),
    //allowin
    .ms_allowin     (ms_allowin     ),
    .es_allowin     (es_allowin     ),
    //from ds
    .ds_to_es_valid (ds_to_es_valid ),
    .ds_to_es_bus   (ds_to_es_bus   ),
    //to ms
    .es_to_ms_valid (es_to_ms_valid ),
    .es_to_ms_bus   (es_to_ms_bus   ),
    //to id
    .es_to_id_bus (es_to_id_bus),
    // data sram interface
    .data_sram_req  (data_sram_req  ),
    .data_sram_wr   (data_sram_wr   ),
    .data_sram_wstrb(data_sram_wstrb),
    .data_sram_addr (data_sram_addr ),
    .data_sram_wdata(data_sram_wdata),
    .data_sram_size (data_sram_size ),
    .data_sram_addr_ok(data_sram_addr_ok),
    //csr data conflict
    .read_csr       (es_read_csr    ),
    //ex
    .ws_ex          (ws_ex          ),
    .ws_ertn_flush     (ws_ertn_flush  ),
    .ms_ex          (ms_ex          ),
    .ms_ertn_flush  (ms_ertn_flush  )
);
// MEM stage
mem_stage mem_stage(
    .clk            (clk            ),
    .reset          (reset          ),
    //allowin
    .ws_allowin     (ws_allowin     ),
    .ms_allowin     (ms_allowin     ),
    //from es
    .es_to_ms_valid (es_to_ms_valid ),
    .es_to_ms_bus   (es_to_ms_bus   ),
    //to ws
    .ms_to_ws_valid (ms_to_ws_valid ),
    .ms_to_ws_bus   (ms_to_ws_bus   ),
    //to id
    .ms_to_id_bus   (ms_to_id_bus),
    //from data-sram
    .data_sram_rdata(data_sram_rdata),
    .data_sram_data_ok(data_sram_data_ok),
    //csr data conflict
    .read_csr       (ms_read_csr    ),
    //ex input
    .ws_ex          (ws_ex          ),
    .ws_ertn_flush  (ws_ertn_flush     ),
    //ex output
    .ms_ex_out      (ms_ex          ),
    .ms_ertn_flush  (ms_ertn_flush  )
);
// WB stage
wb_stage wb_stage(
    .clk            (clk            ),
    .reset          (reset          ),
    //allowin
    .ws_allowin     (ws_allowin     ),
    //from ms
    .ms_to_ws_valid (ms_to_ws_valid ),
    .ms_to_ws_bus   (ms_to_ws_bus   ),
    //to rf: for write back
    .ws_to_id_bus   (ws_to_id_bus   ),
    //trace debug interface
    .debug_wb_pc      (debug_wb_pc      ),
    .debug_wb_rf_we  (debug_wb_rf_we  ),
    .debug_wb_rf_wnum (debug_wb_rf_wnum ),
    .debug_wb_rf_wdata(debug_wb_rf_wdata),
    //csr
    .csr_num        (csr_num        ),
    .csr_we_out     (csr_we         ),
    .csr_rvalue     (csr_rvalue     ),
    .csr_wvalue     (csr_wvalue     ),
    .csr_wmask      (csr_wmask      ),
    //csr data conflict
    .read_csr       (ws_read_csr    ),
    //ex
    .ws_ex_out      (ws_ex          ),
    .ws_ertn_flush     (ws_ertn_flush     ),
    .Ecode          (ws_ecode       ),
    .EsubCode       (ws_esubcode    ),
    .ws_vaddr       (ws_vaddr       )
);

//csr
csr csr(
    .clk            (clk            ),
    .reset          (reset          ),
//sent by ws
    //csr read & write
    .csr_num        (csr_num        ),
    .csr_we         (csr_we         ),
    .csr_wvalue     (csr_wvalue     ),
    .csr_wmask      (csr_wmask      ),
//send to ws
    //csr read
    .csr_rvalue     (csr_rvalue     ),
//ex
    .ex_entry       (ex_entry       ),
    .ws_ex          (ws_ex          ),
    .ws_pc          (debug_wb_pc    ),
    .ws_ecode       (ws_ecode       ),
    .ws_esubcode    (ws_esubcode    ),
    
    .ertn_flush     (ws_ertn_flush  ),
    .era_entry      (era_entry      ),
    .has_int        (has_int        ),
    .ws_vaddr       (ws_vaddr       )
);

endmodule